home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / sfnt / sfobjs.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  23.6 KB  |  703 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  sfobjs.c                                                               */
  4. /*                                                                         */
  5. /*    SFNT object management (base).                                       */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include "sfobjs.h"
  21. #include "ttload.h"
  22. #include FT_INTERNAL_SFNT_H
  23. #include FT_INTERNAL_POSTSCRIPT_NAMES_H
  24. #include FT_TRUETYPE_IDS_H
  25. #include FT_TRUETYPE_TAGS_H
  26.  
  27. #include "sferrors.h"
  28.  
  29.  
  30.   /*************************************************************************/
  31.   /*                                                                       */
  32.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  33.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  34.   /* messages during execution.                                            */
  35.   /*                                                                       */
  36. #undef  FT_COMPONENT
  37. #define FT_COMPONENT  trace_sfobjs
  38.  
  39.  
  40.   /*************************************************************************/
  41.   /*                                                                       */
  42.   /* <Function>                                                            */
  43.   /*    Get_Name                                                           */
  44.   /*                                                                       */
  45.   /* <Description>                                                         */
  46.   /*    Returns a given ENGLISH name record in ASCII.                      */
  47.   /*                                                                       */
  48.   /* <Input>                                                               */
  49.   /*    face   :: A handle to the source face object.                      */
  50.   /*                                                                       */
  51.   /*    nameid :: The name id of the name record to return.                */
  52.   /*                                                                       */
  53.   /* <Return>                                                              */
  54.   /*    Character string.  NULL if no name is present.                     */
  55.   /*                                                                       */
  56.   static FT_String*
  57.   Get_Name( TT_Face    face,
  58.             FT_UShort  nameid )
  59.   {
  60.     FT_Memory    memory = face->root.memory;
  61.     FT_UShort    n;
  62.     TT_NameRec*  rec;
  63.     FT_Bool      wide_chars    = 1;
  64.     FT_Int       found_apple   = -1;
  65.     FT_Int       found_win     = -1;
  66.     FT_Int       found_unicode = -1;
  67.     FT_Int       found;
  68.  
  69.  
  70.     rec = face->name_table.names;
  71.     for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ )
  72.     {
  73.       if ( rec->nameID == nameid && rec->string )
  74.       {
  75.         switch ( rec->platformID )
  76.         {
  77.           case TT_PLATFORM_APPLE_UNICODE:
  78.             {
  79.               found_unicode = n;
  80.               break;
  81.             }
  82.             
  83.           case TT_PLATFORM_MACINTOSH:
  84.             {
  85.               if ( rec->languageID == TT_MAC_ID_ROMAN )
  86.                 found_apple = n;
  87.               
  88.               break;
  89.             }
  90.             
  91.           case TT_PLATFORM_MICROSOFT:
  92.             {
  93.               if (  rec->encodingID <= TT_MS_ID_UNICODE_CS &&
  94.                    (rec->languageID & 0x3FF) == 0x009      )
  95.               {
  96.                 found_win = n;
  97.               }
  98.               break;
  99.             }
  100.           
  101.           default:
  102.             ;
  103.         }
  104.       }
  105.     }
  106.  
  107.     /* some fonts contain invalid Unicode or Macintosh formatted entries */
  108.     /* we will thus favor name encoded in Windows formats when they're   */
  109.     /* available..                                                       */
  110.     /*                                                                   */
  111.     found = found_win;
  112.     if ( found < 0 )
  113.     {
  114.       found = found_apple;
  115.       if ( found_apple < 0 )
  116.         found = found_unicode;
  117.       else
  118.         wide_chars = 0;
  119.     }
  120.  
  121.     /* found a Unicode name */
  122.     if ( found >= 0 )
  123.     {
  124.       FT_String*  string;
  125.       FT_UInt     len;
  126.  
  127.       rec = face->name_table.names + found;
  128.       if ( wide_chars )
  129.       {
  130.         FT_UInt   m;
  131.  
  132.  
  133.         len = (FT_UInt)rec->stringLength / 2;
  134.         if ( MEM_Alloc( string, len + 1 ) )
  135.           return NULL;
  136.  
  137.         for ( m = 0; m < len; m ++ )
  138.           string[m] = rec->string[2 * m + 1];
  139.       }
  140.       else
  141.       {
  142.         len = rec->stringLength;
  143.         if ( MEM_Alloc( string, len + 1 ) )
  144.           return NULL;
  145.  
  146.         MEM_Copy( string, rec->string, len );
  147.       }
  148.  
  149.       string[len] = '\0';
  150.       return string;
  151.     }
  152.  
  153.     return NULL;
  154.   }
  155.  
  156.  
  157.   static FT_Encoding
  158.   find_encoding( int  platform_id,
  159.                  int  encoding_id )
  160.   {
  161.     typedef struct  TEncoding
  162.     {
  163.       int          platform_id;
  164.       int          encoding_id;
  165.       FT_Encoding  encoding;
  166.  
  167.     } TEncoding;
  168.  
  169.     static
  170.     const TEncoding  tt_encodings[] =
  171.     {
  172.       { TT_PLATFORM_ISO,           -1,                  ft_encoding_unicode },
  173.  
  174.       { TT_PLATFORM_APPLE_UNICODE, -1,                  ft_encoding_unicode },
  175.  
  176.       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     ft_encoding_apple_roman },
  177.  
  178.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  ft_encoding_symbol },
  179.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      ft_encoding_unicode },
  180.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
  181.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       ft_encoding_sjis },
  182.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     ft_encoding_gb2312 },
  183.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      ft_encoding_big5 },
  184.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    ft_encoding_wansung },
  185.       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      ft_encoding_johab }
  186.     };
  187.  
  188.     const TEncoding  *cur, *limit;
  189.  
  190.  
  191.     cur   = tt_encodings;
  192.     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
  193.  
  194.     for ( ; cur < limit; cur++ )
  195.     {
  196.       if ( cur->platform_id == platform_id )
  197.       {
  198.         if ( cur->encoding_id == encoding_id ||
  199.              cur->encoding_id == -1          )
  200.           return cur->encoding;
  201.       }
  202.     }
  203.  
  204.     return ft_encoding_none;
  205.   }
  206.  
  207.  
  208.   FT_LOCAL_DEF FT_Error
  209.   SFNT_Init_Face( FT_Stream      stream,
  210.                   TT_Face        face,
  211.                   FT_Int         face_index,
  212.                   FT_Int         num_params,
  213.                   FT_Parameter*  params )
  214.   {
  215.     FT_Error            error;
  216.     FT_Library          library = face->root.driver->root.library;
  217.     SFNT_Interface*     sfnt;
  218.     SFNT_Header         sfnt_header;
  219.  
  220.     /* for now, parameters are unused */
  221.     FT_UNUSED( num_params );
  222.     FT_UNUSED( params );
  223.  
  224.     sfnt = (SFNT_Interface*)face->sfnt;
  225.     if ( !sfnt )
  226.     {
  227.       sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
  228.       if ( !sfnt )
  229.       {
  230.         error = SFNT_Err_Invalid_File_Format;
  231.         goto Exit;
  232.       }
  233.  
  234.       face->sfnt       = sfnt;
  235.       face->goto_table = sfnt->goto_table;
  236.     }
  237.  
  238.     if ( !face->psnames )
  239.     {
  240.       face->psnames = (PSNames_Interface*)
  241.                        FT_Get_Module_Interface( library, "psnames" );
  242.     }
  243.  
  244.     /* check that we have a valid TrueType file */
  245.     error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
  246.     if ( error )
  247.       goto Exit;
  248.  
  249.     face->format_tag = sfnt_header.format_tag;
  250.     face->num_tables = sfnt_header.num_tables;
  251.  
  252.     /* Load font directory */
  253.     error = sfnt->load_directory( face, stream, &sfnt_header );
  254.     if ( error )
  255.       goto Exit;
  256.  
  257.     face->root.num_faces = face->ttc_header.count;
  258.     if ( face->root.num_faces < 1 )
  259.       face->root.num_faces = 1;
  260.  
  261.   Exit:
  262.     return error;
  263.   }
  264.  
  265.  
  266. #undef  LOAD_
  267. #define LOAD_( x )  ( ( error = sfnt->load_##x( face, stream ) ) \
  268.                       != SFNT_Err_Ok )
  269.  
  270.  
  271.   FT_LOCAL_DEF FT_Error
  272.   SFNT_Load_Face( FT_Stream      stream,
  273.                   TT_Face        face,
  274.                   FT_Int         face_index,
  275.                   FT_Int         num_params,
  276.                   FT_Parameter*  params )
  277.   {
  278.     FT_Error         error;
  279.     FT_Bool          has_outline;
  280.     FT_Bool          is_apple_sbit;
  281.  
  282.     SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
  283.  
  284.     FT_UNUSED( face_index );
  285.     FT_UNUSED( num_params );
  286.     FT_UNUSED( params );
  287.  
  288.  
  289.     /* Load tables */
  290.  
  291.     /* We now support two SFNT-based bitmapped font formats.  They */
  292.     /* are recognized easily as they do not include a `glyf'       */
  293.     /* table.                                                      */
  294.     /*                                                             */
  295.     /* The first format comes from Apple, and uses a table named   */
  296.     /* `bhed' instead of `head' to store the font header (using    */
  297.     /* the same format).  It also doesn't include horizontal and   */
  298.     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
  299.     /* missing).                                                   */
  300.     /*                                                             */
  301.     /* The other format comes from Microsoft, and is used with     */
  302.     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
  303.     /* it doesn't contain outlines.                                */
  304.     /*                                                             */
  305.  
  306.     /* do we have outlines in there? */
  307.     has_outline   = FT_BOOL( ( TT_LookUp_Table( face, TTAG_glyf ) != 0 ) ||
  308.                              ( TT_LookUp_Table( face, TTAG_CFF  ) != 0 ) );
  309.     is_apple_sbit = 0;
  310.  
  311. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  312.  
  313.     /* if this font doesn't contain outlines, we try to load */
  314.     /* a `bhed' table                                        */
  315.     if ( !has_outline )
  316.       is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) );
  317.  
  318. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  319.  
  320.     /* load the font header (`head' table) if this isn't an Apple */
  321.     /* sbit font file                                             */
  322.     if ( !is_apple_sbit && LOAD_( header ) )
  323.       goto Exit;
  324.  
  325.     /* the following tables are often not present in embedded TrueType */
  326.     /* fonts within PDF documents, so don't check for them.            */
  327.     (void)LOAD_( max_profile );
  328.     (void)LOAD_( charmaps );
  329.       
  330.     /* the following tables are optional in PCL fonts -- */
  331.     /* don't check for errors                            */
  332.     (void)LOAD_( names );
  333.     (void)LOAD_( psnames );
  334.  
  335.     /* do not load the metrics headers and tables if this is an Apple */
  336.     /* sbit font file                                                 */
  337.     if ( !is_apple_sbit )
  338.     {
  339.       /* load the `hhea' and `hmtx' tables at once */
  340.       error = sfnt->load_metrics( face, stream, 0 );
  341.       if ( error )
  342.         goto Exit;
  343.  
  344.       /* try to load the `vhea' and `vmtx' tables at once */
  345.       error = sfnt->load_metrics( face, stream, 1 );
  346.       if ( error )
  347.         goto Exit;
  348.  
  349.       if ( LOAD_( os2 ) )
  350.         goto Exit;
  351.     }
  352.  
  353.     /* the optional tables */
  354.  
  355. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  356.  
  357.     /* embedded bitmap support. */
  358.     if ( sfnt->load_sbits && LOAD_( sbits ) )
  359.     {
  360.       /* return an error if this font file has no outlines */
  361.       if ( error == SFNT_Err_Table_Missing && has_outline )
  362.         error = SFNT_Err_Ok;
  363.       else
  364.         goto Exit;
  365.     }
  366. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  367.  
  368.     if ( LOAD_( hdmx )    ||
  369.          LOAD_( gasp )    ||
  370.          LOAD_( kerning ) ||
  371.          LOAD_( pclt )    )
  372.       goto Exit;
  373.  
  374. #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
  375.     if ( ( error = TT_Extension_Create( face ) ) != SFNT_Err_Ok )
  376.       goto Exit;
  377. #endif
  378.  
  379.     face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY );
  380.     face->root.style_name  = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY );
  381.  
  382.     /* now set up root fields */
  383.     {
  384.       FT_Face     root = &face->root;
  385.       FT_Int      flags = 0;
  386.       TT_CharMap  charmap;
  387.       FT_Int      n;
  388.       FT_Memory   memory;
  389.  
  390.  
  391.       memory = root->memory;
  392.  
  393.       /*********************************************************************/
  394.       /*                                                                   */
  395.       /* Compute face flags.                                               */
  396.       /*                                                                   */
  397.       if ( has_outline == TRUE )
  398.         flags = FT_FACE_FLAG_SCALABLE;    /* scalable outlines */
  399.  
  400.       flags |= FT_FACE_FLAG_SFNT      |   /* SFNT file format  */
  401.                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
  402.  
  403. #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
  404.       /* might need more polish to detect the presence of a Postscript */
  405.       /* name table in the font                                        */
  406.       flags |= FT_FACE_FLAG_GLYPH_NAMES;
  407. #endif
  408.  
  409.       /* fixed width font? */
  410.       if ( face->postscript.isFixedPitch )
  411.         flags |= FT_FACE_FLAG_FIXED_WIDTH;
  412.  
  413.       /* vertical information? */
  414.       if ( face->vertical_info )
  415.         flags |= FT_FACE_FLAG_VERTICAL;
  416.  
  417.       /* kerning available ? */
  418.       if ( face->kern_pairs )
  419.         flags |= FT_FACE_FLAG_KERNING;
  420.  
  421.       root->face_flags = flags;
  422.  
  423.       /*********************************************************************/
  424.       /*                                                                   */
  425.       /* Compute style flags.                                              */
  426.       /*                                                                   */
  427.       flags = 0;
  428.       if ( has_outline == TRUE && face->os2.version != 0xFFFF )
  429.       {
  430.         /* we have an OS/2 table; use the `fsSelection' field */
  431.         if ( face->os2.fsSelection & 1 )
  432.           flags |= FT_STYLE_FLAG_ITALIC;
  433.  
  434.         if ( face->os2.fsSelection & 32 )
  435.           flags |= FT_STYLE_FLAG_BOLD;
  436.       }
  437.       else
  438.       {
  439.         /* this is an old Mac font, use the header field */
  440.         if ( face->header.Mac_Style & 1 )
  441.           flags |= FT_STYLE_FLAG_BOLD;
  442.  
  443.         if ( face->header.Mac_Style & 2 )
  444.           flags |= FT_STYLE_FLAG_ITALIC;
  445.       }
  446.  
  447.       root->style_flags = flags;
  448.  
  449.       /*********************************************************************/
  450.       /*                                                                   */
  451.       /* Polish the charmaps.                                              */
  452.       /*                                                                   */
  453.       /*   Try to set the charmap encoding according to the platform &     */
  454.       /*   encoding ID of each charmap.                                    */
  455.       /*                                                                   */
  456.       charmap            = face->charmaps;
  457.       root->num_charmaps = face->num_charmaps;
  458.  
  459.       /* allocate table of pointers */
  460.       if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
  461.         goto Exit;
  462.  
  463.       for ( n = 0; n < root->num_charmaps; n++, charmap++ )
  464.       {
  465.         FT_Int  platform = charmap->cmap.platformID;
  466.         FT_Int  encoding = charmap->cmap.platformEncodingID;
  467.  
  468.  
  469.         charmap->root.face        = (FT_Face)face;
  470.         charmap->root.platform_id = (FT_UShort)platform;
  471.         charmap->root.encoding_id = (FT_UShort)encoding;
  472.         charmap->root.encoding    = find_encoding( platform, encoding );
  473.  
  474.         /* now, set root->charmap with a unicode charmap */
  475.         /* wherever available                            */
  476.         if ( !root->charmap                                &&
  477.              charmap->root.encoding == ft_encoding_unicode )
  478.           root->charmap = (FT_CharMap)charmap;
  479.  
  480.         root->charmaps[n] = (FT_CharMap)charmap;
  481.       }
  482.  
  483. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  484.  
  485.       if ( face->num_sbit_strikes )
  486.       {
  487.         root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
  488.  
  489. #if 0
  490.         /* I don't know criteria whether layout is horizontal or vertical */
  491.         if ( has_outline.... )
  492.         {
  493.           ...
  494.           root->face_flags |= FT_FACE_FLAG_VERTICAL;
  495.         }
  496. #endif
  497.         root->num_fixed_sizes = face->num_sbit_strikes;
  498.  
  499.         if ( ALLOC_ARRAY( root->available_sizes,
  500.                           face->num_sbit_strikes,
  501.                           FT_Bitmap_Size ) )
  502.           goto Exit;
  503.  
  504.         for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
  505.         {
  506.           root->available_sizes[n].width =
  507.             face->sbit_strikes[n].x_ppem;
  508.  
  509.           root->available_sizes[n].height =
  510.             face->sbit_strikes[n].y_ppem;
  511.         }
  512.       }
  513.       else
  514.  
  515. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  516.  
  517.       {
  518.         root->num_fixed_sizes = 0;
  519.         root->available_sizes = 0;
  520.       }
  521.  
  522.       /*********************************************************************/
  523.       /*                                                                   */
  524.       /*  Set up metrics.                                                  */
  525.       /*                                                                   */
  526.       if ( has_outline == TRUE )
  527.       {
  528.         /* XXX What about if outline header is missing */
  529.         /*     (e.g. sfnt wrapped outline)?            */
  530.         root->bbox.xMin    = face->header.xMin;
  531.         root->bbox.yMin    = face->header.yMin;
  532.         root->bbox.xMax    = face->header.xMax;
  533.         root->bbox.yMax    = face->header.yMax;
  534.         root->units_per_EM = face->header.Units_Per_EM;
  535.  
  536.  
  537.         /* XXX: Computing the ascender/descender/height is very different */
  538.         /*      from what the specification tells you.  Apparently, we    */
  539.         /*      must be careful because                                   */
  540.         /*                                                                */
  541.         /*      - not all fonts have an OS/2 table; in this case, we take */
  542.         /*        the values in the horizontal header.  However, these    */
  543.         /*        values very often are not reliable.                     */
  544.         /*                                                                */
  545.         /*      - otherwise, the correct typographic values are in the    */
  546.         /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
  547.         /*                                                                */
  548.         /*        However, certains fonts have these fields set to 0.     */
  549.         /*        Rather, they have usWinAscent & usWinDescent correctly  */
  550.         /*        set (but with different values).                        */
  551.         /*                                                                */
  552.         /*      As an example, Arial Narrow is implemented through four   */
  553.         /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
  554.         /*                                                                */
  555.         /*      Strangely, all fonts have the same values in their        */
  556.         /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
  557.         /*                                                                */
  558.         /*      On the other hand, they all have different                */
  559.         /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
  560.         /*      table cannot be used to compute the text height reliably! */
  561.         /*                                                                */
  562.  
  563.         /* The ascender/descender/height are computed from the OS/2 table */
  564.         /* when found.  Otherwise, they're taken from the horizontal      */
  565.         /* header.                                                        */
  566.         /*                                                                */
  567.  
  568.         root->ascender  = face->horizontal.Ascender;
  569.         root->descender = face->horizontal.Descender;
  570.  
  571.         root->height    = (FT_Short)( root->ascender - root->descender +
  572.                                       face->horizontal.Line_Gap );
  573.  
  574.         /* if the line_gap is 0, we add an extra 15% to the text height --  */
  575.         /* this computation is based on various versions of Times New Roman */
  576.         if ( face->horizontal.Line_Gap == 0 )
  577.           root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
  578.  
  579. #if 0
  580.  
  581.         /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
  582.         /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
  583.         if ( face->os2.version != 0xFFFF && root->ascender )
  584.         {
  585.           FT_Int  height;
  586.  
  587.  
  588.           root->ascender  =  face->os2.sTypoAscender;
  589.           root->descender = -face->os2.sTypoDescender;
  590.  
  591.           height = root->ascender + root->descender + face->os2.sTypoLineGap;
  592.           if ( height > root->height )
  593.             root->height = height;
  594.         }
  595.  
  596. #endif /* 0 */
  597.  
  598.         root->max_advance_width   = face->horizontal.advance_Width_Max;
  599.  
  600.         root->max_advance_height  = (FT_Short)( face->vertical_info
  601.                                       ? face->vertical.advance_Height_Max
  602.                                       : root->height );
  603.  
  604.         root->underline_position  = face->postscript.underlinePosition;
  605.         root->underline_thickness = face->postscript.underlineThickness;
  606.  
  607.         /* root->max_points   -- already set up */
  608.         /* root->max_contours -- already set up */
  609.       }
  610.     }
  611.  
  612.   Exit:
  613.     return error;
  614.   }
  615.  
  616.  
  617. #undef LOAD_
  618.  
  619.  
  620.   FT_LOCAL_DEF void
  621.   SFNT_Done_Face( TT_Face  face )
  622.   {
  623.     FT_Memory        memory = face->root.memory;
  624.     SFNT_Interface*  sfnt   = (SFNT_Interface*)face->sfnt;
  625.  
  626.  
  627.     if ( sfnt )
  628.     {
  629.       /* destroy the postscript names table if it is loaded */
  630.       if ( sfnt->free_psnames )
  631.         sfnt->free_psnames( face );
  632.  
  633.       /* destroy the embedded bitmaps table if it is loaded */
  634.       if ( sfnt->free_sbits )
  635.         sfnt->free_sbits( face );
  636.     }
  637.  
  638.     /* freeing the kerning table */
  639.     FREE( face->kern_pairs );
  640.     face->num_kern_pairs = 0;
  641.  
  642.     /* freeing the collection table */
  643.     FREE( face->ttc_header.offsets );
  644.     face->ttc_header.count = 0;
  645.  
  646.     /* freeing table directory */
  647.     FREE( face->dir_tables );
  648.     face->num_tables = 0;
  649.  
  650.     /* freeing the character mapping tables */
  651.     if ( sfnt && sfnt->load_charmaps )
  652.     {
  653.       FT_UShort  n;
  654.  
  655.  
  656.       for ( n = 0; n < face->num_charmaps; n++ )
  657.         sfnt->free_charmap( face, &face->charmaps[n].cmap );
  658.     }
  659.  
  660.     FREE( face->charmaps );
  661.     face->num_charmaps = 0;
  662.  
  663.     FREE( face->root.charmaps );
  664.     face->root.num_charmaps = 0;
  665.     face->root.charmap      = 0;
  666.  
  667.     /* freeing the horizontal metrics */
  668.     FREE( face->horizontal.long_metrics );
  669.     FREE( face->horizontal.short_metrics );
  670.  
  671.     /* freeing the vertical ones, if any */
  672.     if ( face->vertical_info )
  673.     {
  674.       FREE( face->vertical.long_metrics  );
  675.       FREE( face->vertical.short_metrics );
  676.       face->vertical_info = 0;
  677.     }
  678.  
  679.     /* freeing the gasp table */
  680.     FREE( face->gasp.gaspRanges );
  681.     face->gasp.numRanges = 0;
  682.  
  683.     /* freeing the name table */
  684.     sfnt->free_names( face );
  685.  
  686.     /* freeing the hdmx table */
  687.     sfnt->free_hdmx( face );
  688.  
  689.     /* freeing family and style name */
  690.     FREE( face->root.family_name );
  691.     FREE( face->root.style_name );
  692.  
  693.     /* freeing sbit size table */
  694.     face->root.num_fixed_sizes = 0;
  695.     if ( face->root.available_sizes )
  696.       FREE( face->root.available_sizes );
  697.  
  698.     face->sfnt = 0;
  699.   }
  700.  
  701.  
  702. /* END */
  703.